-------------------模块区-------------------
local dx_mqtt = require("dx_mqtt")
local dx_map = require("dx_map")
local dx_queue = require("dx_queue")
local log = require("mylog")
local dx_json = require("dx_json")
local string_util = require("string_util")
local number_util = require("number_util")
local os_util = require("os_util")
local mqtt_service = require("mqtt_service")
local config = require("config")
local dx_gpio = require("dx_gpio")
require("update_config")

-------------------变量区-------------------
local mqtt_common = {}
-- 初始化连接状态为true，如果接收到quit消息则赋值为false
local running = true

-------------------函数区-------------------
-- 处理订阅消息
local function callback(topic, payload)
    if (payload == "quit") then
        log.warn("[mqtt]链接掉线")
        running = false
        return 0
    end

    dx_map.set(_G_map, "mqtt_dog", "Y")

    local topic_by_map = dx_map.get(mqtt_service.topic_set_map, topic)
    if topic_by_map ~= nil and topic_by_map ~= "" then
        local ret = mqtt_service[dx_map.get(mqtt_service.topic_set_map, topic)](payload)
        if not ret then
            if topic ~= mqtt_service.topics.EVENT_TOPIC_LOG then
                -- 避免日志上报陷入循环
                log.error("消息处理异常topic：" .. topic .. "，payload：" .. payload)
            end
        end
    else
        log.info("没有该请求类型topic：" .. topic .. "，payload：" .. payload)
    end
end

function mqtt_common.create_client(args)
    -- 创建client
    _G.mqtt_client = dx_mqtt.client.create(args.host, args.port, callback)
    log.info("[mqtt_client]创建完成")
end

function mqtt_common.create_connect(args)
    -- 建立mqtt连接

    dx_map.set(_G_map, "mqtt_dog", "Y")
    local connect_error = mqtt_client:connect(args.id)
    while connect_error ~= nil do
        os.execute("sleep " .. 1)
        connect_error = mqtt_client:connect(args.id)

        -- 等待建立mqtt连接也要喂狗
        dx_map.set(_G_map, "mqtt_dog", "Y")
    end
    dx_map.set(_G_map, "mqtt_connect_ing", "Y")
    -- 连接成功，上送设备信息
    mqtt_service[dx_map.get(mqtt_service.topic_set_map, mqtt_service.topics.EVENT_TOPIC_CONNECT)]()
    log.info("[mqtt链接]初始化完成")
end

function mqtt_common.create_subscribe()
    -- 添加订阅
    mqtt_client:subscribe(mqtt_service.subscribe)
    log.info("[mqtt消息订阅]初始化完成")
end

function mqtt_common.Keep_alive(args)
    local error_message = nil
    local running = true
    config.configStrToTable()
    while (error_message == nil and running) do
        error_message = mqtt_client:handler()
        if (error_message == nil) then
            local mqtt_msg = dx_queue.pop(mqtt_queue, 500)
            if mqtt_msg ~= nil and string_util.split(mqtt_msg, "####")[2] then
                if string_util.split(mqtt_msg, "####")[1] ~= mqtt_service.topics.EVENT_TOPIC_LOG then
                    -- 避免日志上报陷入循环
                    log.info("接收到需要处理的mqtt请求：", mqtt_msg)
                end
                mqtt_common.mqtt_queue_handler(mqtt_msg)
            end
            os_util.sleep(0.01)
            -- 网络灯打开
            if not g_config["mqtt_con_status"] then
                g_config["mqtt_con_status"] = true
                config.configTableToStr()
                dx_gpio.gpio_set_value(73, 1)
            end
        end
        dx_map.set(_G_map, "mqtt_dog", "Y")
    end
    return error_message
end

function mqtt_common.mqtt_queue_handler(mqtt_msg)
    local mqtt_msgs = string_util.split(mqtt_msg, "####")
    if #mqtt_msgs ~= 2 then
        return nil
    end
    callback(mqtt_msgs[1], mqtt_msgs[2])
end

function mqtt_common.error(error_message, args)
    -- mqtt断连,网络灯关闭
    config.configStrToTable()
    g_config["mqtt_con_status"] = false
    config.configTableToStr()
    dx_gpio.gpio_set_value(73, 0)
    -- mqtt服务停止，判断是否正常停止
    if (error_message == nil) then
        mqtt_client:unsubscribe({args.topic_s})
        mqtt_client:destroy()
        log.info("mqtt服务停止，订阅&链接已释放")
        return false
    else
        log.error("mqtt通道异常：", error_message)
        return true
    end
end

function mqtt_common.mqtt_init()
    -- 无法将mqtt通道指定给全局map，所以需要监听堵塞队列进行消费发送消息请求
    _G._G_map = _G["_G_map"]
    _G.mqtt_queue = dx_map.get(_G_map, "mqtt_queue")
    -- 全局sqlite实例
    _G.sqlite_client = dx_map.get(_G_map, "sqlite_client")

    -- 从全局map中取出我们存储的g_config
    local g_config_str = dx_map.get(_G_map, "g_config_str")
    log.info("[mqtt_init]从MQTT线程中获取g_config配置: ", g_config_str)
    _G.g_config = dx_json.decode(g_config_str)

    g_config["mqtt_dog"] = true
    -- ret = writecfg()
    -- 把最新的配置信息存储到全局MAP中
    config.configTableToStr()

    -- mqtt链接信息，测试地址
    local args = {
        host = g_config.mqttAddr,
        port = g_config.port,
        id = g_config.clientId,
        debug = true
    }
    local flag = true
    while flag do
        mqtt_common.create_client(args)
        mqtt_common.create_connect(args)
        mqtt_common.create_subscribe()
        local error_message = mqtt_common.Keep_alive(args)
        flag = mqtt_common.error(error_message, args)
        os_util.sleep(2)
        -- 等待建立mqtt连接也要喂狗
        dx_map.set(_G_map, "mqtt_dog", "Y")
    end
end

-------------------主流程-------------------
mqtt_common.mqtt_init()

return mqtt_common
